#include "dht11.h"
#include <stdio.h>

/**
 * @brief 读取 dht11 温湿度
 * @return int
 *         OK 成功
 *         EINVAL 无效的参数
 *         ECHECKSUM 数据校验失败
 *         ETIMEOUT 读取超时
 */
int dht11_read(struct dht11* sensor, uint8_t* temp, uint8_t* hum)
{
        uint8_t data[5] = { 0 };
        uint8_t cnt = 7;
        uint8_t idx = 0;
        uint8_t sum = 0;
        uint32_t loop = 0;

        if (!sensor || !temp || !hum) {
                return EINVAL;
        }

        /* request sample */
        if (sensor->wire.dir_set) {
                sensor->wire.dir_set(OUTPUT);
        }
        sensor->wire.write(LOW);
        sensor->time.delay_ms(25);
        sensor->wire.write(HIGH);
        sensor->time.delay_us(40);
        if (sensor->wire.dir_set) {
                sensor->wire.dir_set(INPUT);
        }

        /* acknowledge or timeout */
        loop = 100000;
        while (sensor->wire.read() == LOW) {
                if (loop-- == 0) {
                        return ETIMEOUT;
                }
        }

        loop = 100000;
        while (sensor->wire.read() == HIGH) {
                if (loop-- == 0) {
                        return ETIMEOUT;
                }
        }

        /* read output - 40 data => 5 bytes or timeout */
        for (int i = 0; i < 40; i++) {
                loop = 100000;
                while (sensor->wire.read() == LOW) {
                        if (loop-- == 0) {
                                return ETIMEOUT;
                        }
                }

                uint64_t t = sensor->time.get();
                loop = 100000;
                while (sensor->wire.read() == HIGH) {
                        if (loop-- == 0) {
                                return ETIMEOUT;
                        }
                }

                if ((sensor->time.get() - t) > 40) {
                        data[idx] |= (1 << cnt);
                }

                if (cnt == 0) {
                        cnt = 7; /* restart at MSB */
                        idx++; /* next byte! */
                } else {
                        cnt--;
                }
        }

        /* write to right vars: as data[1] and data[3] are allways zero */
        *hum = data[0];
        *temp = data[2];

        sum = data[0] + data[2];
        if (data[4] != sum)
                return ECHECKSUM;

        return OK;
}
